using System.Linq;
using Castle.DynamicProxy;
using EntityAop.Interceptors.InterfacesToImplement;
using EntityAop.Interceptors.Support;

namespace EntityAop.Interceptors
{
    public class SetNotifyingInterceptor : BaseInterceptor
    {
        protected override void PerformProceed(IInvocation invocation)
        {
            var propertyName = invocation.Method.Name.Substring("set_".Length);

            var methodNameStartsWithSet = invocation.Method.Name.StartsWith("set_");

            if (methodNameStartsWithSet)
            {
                var targetValue = invocation.TargetType
                    .GetProperty(propertyName)
                    .GetValue(invocation.InvocationTarget, null);

                // the value setted is the same, so no NPC calling
                if (invocation.Arguments.Count() == 1 && targetValue == invocation.Arguments[0])
                {
                    return;
                }


                var targetValueAsINotifyOfPropertyChange = targetValue as INotifyOfPropertyChange;
                if (targetValueAsINotifyOfPropertyChange != null)
                {
                    InstanceSpecificHelper.UnRegisterInverseReference(invocation);
                }
            }

            base.PerformProceed(invocation);

            if (Configuration.IsInProxyCreationPhase)
            {
                return;
            }

            if (methodNameStartsWithSet)
            {
                NotificationHelper.ProceedSetterNotifications(invocation, propertyName);
            }
        }
    }

    public class TargetAccessorInterceptor : BaseInterceptor
    {
        public TargetAccessorInterceptor()
            : base()
        {
            RelatedTypes = new[] { typeof(ITargetAccessor)};
        }
        protected override void PerformProceed(IInvocation invocation)
        {
            invocation.ReturnValue = InvocationHelper.GetInvocationTarget(invocation);
        }
    }
}